/**
 * \brief   base64公共接口，此文件内所有接口不分操作系统
*/

#include "common_interface.h"
#include "common_errno.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>

static char global_static_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static int global_static_get_decode_number(char decode) {
    int i;
    for(i = 0; i < 64; i++) {
        if(decode == global_static_base64[i]) {
            return i;
        }
        else if(decode == '=') {
            return 0;
        }
    }
    return -1;
}

int base64_encode(char out[], int *olen, int osize, char in[], int inlen) {
    int temp = 0;
    int i;
    int j;
    int outlen = 0;
    char arr[3] = { 0 };

    if(out == NULL || olen == NULL || osize <= 0 || in == NULL || inlen <= 0) {
        return COM_BAD_INPUT;
    }

    if(inlen % 3 == 0) {
        temp = (inlen / 3) * 4;
    }
    else {  //补位的情况
        temp = ((inlen / 3) * 4) + 4;
    }
    if(temp > osize) {
        return COM_BUF_SMALL;
    }
    for(i = 0; i < inlen; i+=3) {
        memset(arr, 0, sizeof(arr));    
        for(j = i; j < i + 3; j++) {
            arr[j - i] = in[j];
        }

        out[outlen] = global_static_base64[arr[0] >> 2];
        out[outlen + 1] = global_static_base64[((arr[0] & 0x03) << 4) | ((arr[1] >> 4))];
        out[outlen + 2] = global_static_base64[((arr[1] & 0x0f) << 2) | ((arr[2] >> 6))];
        out[outlen + 3] = global_static_base64[arr[2] & 0x3f];
        outlen = outlen + 4;
    }
    *olen = outlen;
    if(inlen % 3 != 0) {
        for(i = 0; i < 3 - (inlen % 3); i++) {
            out[outlen - 1 - i] = '=';
        }
    }
    return COM_OK;
}

int base64_decode(char out[], int *olen, int osize, char in[], int inlen) {
    int temp = 0;
    int i, j;
    int outlen = 0;
    char arr[4] = { 0 };

    if(out == NULL || olen == NULL || osize <= 0 || in == NULL || inlen <= 0) {
        return COM_BAD_INPUT;
    }

    if(inlen % 4 == 0) {
        temp = (inlen / 4) * 3;
    }
    else {
        temp = ((inlen / 4) * 3) + 3;
    }
    if(temp > osize) {
        return COM_BUF_SMALL;
    }

    for(i = 0; i < inlen; i+=4) {
        memset(arr, 0, sizeof(arr));
        //赋值到arr当中
        for(j = i; j < i + 4; j++) {
            arr[j - i] = in[j];
        }
        out[outlen] = (global_static_get_decode_number(arr[0]) << 2) | ((global_static_get_decode_number(arr[1]) & 0x30) >> 4);
        out[outlen + 1] = (global_static_get_decode_number(arr[1]) << 4) | ((global_static_get_decode_number(arr[2]) & 0x3c) >> 2);
        out[outlen + 2] = (global_static_get_decode_number(arr[2]) << 6) | (global_static_get_decode_number(arr[3]) & 0x3f);
        outlen = outlen + 3;
    }
    *olen = outlen;
    return COM_OK;
}